package com.xxkk.gameCore.global.globalServer;

import com.xxkk.gameCore.net.sql.mapper.AreaInfoMapper;
import com.xxkk.gameCore.net.sql.mapper.ServerInfoMapper;
import com.xxkk.gameCore.net.sql.pojo.AreaInfo;
import com.xxkk.gameCore.net.sql.pojo.AreaInfoExample;
import com.xxkk.gameCore.net.sql.pojo.ServerInfo;
import com.xxkk.gameCore.net.sql.pojo.ServerInfoExample;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.*;

/**
 * @author xxkk
 * @version 1.0.0
 * @title ServerData
 * @description ʕ•ᴥ•ʔ
 * @create 2023/11/13 09:53
 **/
@Component
public class ServerData {
    private Map<Integer, ServerInfo> serverInfoMap;
    private Map<Integer, AreaInfo> areaInfoMap;
    private ServerInfo selfServerInfo;

//    private boolean isInitArea = false;

    @Autowired
    private ServerInfoMapper serverInfoMapper;
    @Autowired
    private AreaInfoMapper areaInfoMapper;
    @Autowired
    private ServerContext serverContext;

    public void init() {
        refreshServerInfo();// 刷新mysql中获取的服务器信息
    }

    private void loadSelfServerInfo() {// 加载本机服务器信息
        try {
            boolean initSuccess = false;
            Enumeration<NetworkInterface> localInterface = NetworkInterface.getNetworkInterfaces();
            Himeka:
            while (localInterface.hasMoreElements()) {
                NetworkInterface ne = localInterface.nextElement();
                Enumeration<InetAddress> ips = ne.getInetAddresses();
                while (ips.hasMoreElements()) {
                    InetAddress address = ips.nextElement();
                    String ip = address.getHostAddress();
                    for (ServerInfo serverInfo : this.serverInfoMap.values()) {
                        if (serverInfo.getIp().equals(ip)) {
                            initSuccess = true;
                            this.selfServerInfo = serverInfo;
                            break Himeka;
                        }
                    }
                }
            }
            if (!initSuccess) {
                System.out.println("#初始化mysql Himeka t_server_info 配置错误");
                System.exit(-1);
            }
        } catch (SocketException e) {
            throw new RuntimeException(e);
        }

    }

    public void refreshServerInfo() {
        Map<Integer, ServerInfo> serverInfoMap = new HashMap<>();
        for (ServerInfo serverInfo : serverInfoMapper.selectByExample(new ServerInfoExample())) {
            serverInfoMap.put(serverInfo.getServerId(), serverInfo);
        }
        this.serverInfoMap = serverInfoMap;

        Map<Integer, AreaInfo> areaInfoMap = new HashMap<>();
        for (AreaInfo areaInfo : areaInfoMapper.selectByExample(new AreaInfoExample())) {
            areaInfoMap.put(areaInfo.getAreaId(), areaInfo);
        }
        this.areaInfoMap = areaInfoMap;

        this.loadSelfServerInfo();
        this.loadSelfAreaContext();
    }

    public void loadSelfAreaContext() {
        for (AreaInfo areaInfo : this.getSelfAreaInfos()) {
            int areaId = areaInfo.getAreaId();
            this.loadGameAreaContext(areaId);
        }
    }

    private void loadGameAreaContext(int areaId) {
        GameAreaContext gameAreaContext = serverContext.getGameAreaContext(areaId);
        if (gameAreaContext == null) {
            gameAreaContext = new GameAreaContext(areaId);
            serverContext.addGameAreaContext(gameAreaContext);
        }
    }

    public List<AreaInfo> getSelfAreaInfos() {
        List<AreaInfo> areaInfos = new ArrayList<>();
        for (AreaInfo areaInfo : this.areaInfoMap.values()) {
            if (Objects.equals(areaInfo.getServerId(), this.selfServerInfo.getServerId()))
                areaInfos.add(areaInfo);
        }
        return areaInfos;
    }

    public ServerInfo getSelfServerInfo() {
        return selfServerInfo;
    }

    /**
     * 为前端提供所有服务器信息
     */
    public List<ServerInfo> getAllServerInfoForFront() {
        List<ServerInfo> serverInfos = new ArrayList<>();
        for (ServerInfo serverInfo : this.serverInfoMap.values()) {
            List<AreaInfo> areaInfoList = this.getAllAreaByServerId(serverInfo.getServerId());
            serverInfo.setAreaInfos(areaInfoList);
            serverInfos.add(serverInfo);
        }
        return serverInfos;
    }

    public List<AreaInfo> getAllAreaByServerId(int serverId) {
        List<AreaInfo> list = new ArrayList<>();
        for (AreaInfo areaInfo : this.areaInfoMap.values()) {
            if (areaInfo.getServerId() == serverId)
                list.add(areaInfo);
        }
        return list;
    }

    public boolean hasSelfArea(int areaId){
        AreaInfo areaInfo = this.areaInfoMap.get(areaId);
        if (areaInfo == null)
            return false;
        return areaInfo.getServerId() == this.selfServerInfo.getServerId();
    }
}
